/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 *
 *           File:  table_gen.h
 *    Description:  CRC table compile-time generator. Use C++ template
 *                  metaprogramming.
 *       
 *        Created:  18.02.2013 20:15:13
 *         Author:  Aleksey Golovchenko (lexgolovchenko@gmail.com)
 *   Organization:  St.Petersburg State Polytecnical Universisy
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef CRC_TABLE_GENERATOR_H_
#define CRC_TABLE_GENERATOR_H_

/*
 * CRC grnrrator polinomial transformation 
 *
 * POLYNOMIAL_GEN - generator polinomial
 */
template <uint32_t t, const uint32_t POLYNOMIAL_GEN>
struct transform_polynome {
    static const uint32_t value = (t & 1) ? ((t >> 1) ^ POLYNOMIAL_GEN) : (t >> 1);
};

/*
 * Compile-time loop implementation
 *
 * POLYNOMIAL_GEN - generator polinomial
 * i - loop iteration index
 */
template <uint32_t t, const uint32_t POLYNOMIAL_GEN, int i> 
struct loop {
    static const uint32_t value = loop< transform_polynome<t, POLYNOMIAL_GEN>::value, POLYNOMIAL_GEN, i-1 >::value; 
};

/*
 * loop stop condition
 */
template <uint32_t t, const uint32_t POLYNOMIAL_GEN> 
struct loop<t, POLYNOMIAL_GEN, 0> {
    static const uint32_t value = transform_polynome<t, POLYNOMIAL_GEN>::value;
};

/*
 * Compile-time calculation cell of table value
 */
template <uint32_t t, const uint32_t POLYNOMIAL_GEN> 
struct table_cell {
    static const uint32_t value = loop<t, POLYNOMIAL_GEN, 7>::value;        
};

/*
 * CRC32 tables
 *
 */
template <int r, uint32_t t, const uint32_t POLYNOMIAL_GEN> 
struct table : table<r+1, t-1, POLYNOMIAL_GEN> {
    table() {
        table<r+1, t-1, POLYNOMIAL_GEN>::values[t] = table_cell<t, POLYNOMIAL_GEN>::value;
    }
};

template <int r, const uint32_t POLYNOMIAL_GEN> 
struct table<r, 0, POLYNOMIAL_GEN> {

    uint32_t values[r+1];
    
    table() {
        values[0] = table_cell<0, POLYNOMIAL_GEN>::value;
    }

	unsigned long operator[](int i) {
		return values[i];
	}
};

template <const uint32_t POLYNOMIAL_GEN> 
struct crc32table : table<0, 255, POLYNOMIAL_GEN> { };

#endif

